bitkeeper revision 1.1159.1.129 (413d868bPMWkW0lZg_MuAYIrmx7XDQ)
authorcl349@freefall.cl.cam.ac.uk <cl349@freefall.cl.cam.ac.uk>
Tue, 7 Sep 2004 09:59:39 +0000 (09:59 +0000)
committercl349@freefall.cl.cam.ac.uk <cl349@freefall.cl.cam.ac.uk>
Tue, 7 Sep 2004 09:59:39 +0000 (09:59 +0000)
Make writable pagetables a domain creation option.

linux-2.6.8.1-xen-sparse/arch/xen/i386/kernel/head.S
linux-2.6.8.1-xen-sparse/arch/xen/i386/kernel/setup.c
xen/arch/x86/domain.c
xen/common/domain.c
xen/common/elf.c
xen/common/kernel.c
xen/include/asm-x86/mm.h
xen/include/xen/elf.h
xen/include/xen/lib.h
xen/include/xen/sched.h

index ff81f18dd90177d132791734eb2083dde91c5349..be45eec5c4a04443979723479d3bb3e11f1d90d5 100644 (file)
@@ -1,9 +1,15 @@
 
+#include <linux/config.h>
+
 .section __xen_guest
-       .asciz "GUEST_OS=linux,GUEST_VER=2.6,XEN_VER=2.0"
+       .ascii  "GUEST_OS=linux,GUEST_VER=2.6,XEN_VER=2.0"
+       .ascii  ",LOADER=generic"
+#ifdef CONFIG_XEN_WRITABLE_PAGETABLES
+       .ascii  ",PT_MODE_WRITABLE"
+#endif
+       .byte   0
 
 .text
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/linkage.h>
 #include <asm/segment.h>
index 1a1c3376d950d698c70c68d768359be16cc0422c..22f1dab651a2287a57427a0ea2e65dbe7ad52979 100644 (file)
@@ -1295,10 +1295,6 @@ void __init setup_arch(char **cmdline_p)
 
        HYPERVISOR_vm_assist(VMASST_CMD_enable,
                             VMASST_TYPE_4gb_segments);
-#ifdef CONFIG_XEN_WRITABLE_PAGETABLES
-       HYPERVISOR_vm_assist(VMASST_CMD_enable,
-                            VMASST_TYPE_writable_pagetables);
-#endif
 
        pm_idle = xen_cpu_idle;
 
index 868a3c97ad21e597fe89be95e05610806881ed3b..d66d407aabcd2baa4e2929fb3f41c0e18aae2b3d 100644 (file)
@@ -557,10 +557,7 @@ int construct_dom0(struct domain *p,
      * *_start address are page-aligned, except v_start (and v_end) which are 
      * superpage-aligned.
      */
-    unsigned long v_start;
-    unsigned long vkern_start;
-    unsigned long vkern_entry;
-    unsigned long vkern_end;
+    struct domain_setup_info dsi;
     unsigned long vinitrd_start;
     unsigned long vinitrd_end;
     unsigned long vphysmap_start;
@@ -584,6 +581,8 @@ int construct_dom0(struct domain *p,
     if ( test_bit(DF_CONSTRUCTED, &p->flags) ) 
         BUG();
 
+    memset(&dsi, 0, sizeof(struct domain_setup_info));
+
     printk("*** LOADING DOMAIN 0 ***\n");
 
     /*
@@ -598,12 +597,11 @@ int construct_dom0(struct domain *p,
      * We'll have to revisit this if we ever support PAE (64GB).
      */
 
-    rc = parseelfimage(image_start, image_len, &v_start,
-                       &vkern_start, &vkern_end, &vkern_entry);
+    rc = parseelfimage(image_start, image_len, &dsi);
     if ( rc != 0 )
         return rc;
 
-    if ( (v_start & (PAGE_SIZE-1)) != 0 )
+    if ( (dsi.v_start & (PAGE_SIZE-1)) != 0 )
     {
         printk("Initial guest OS must load to a page boundary.\n");
         return -EINVAL;
@@ -618,7 +616,7 @@ int construct_dom0(struct domain *p,
      */
     for ( nr_pt_pages = 2; ; nr_pt_pages++ )
     {
-        vinitrd_start    = round_pgup(vkern_end);
+        vinitrd_start    = round_pgup(dsi.v_kernend);
         vinitrd_end      = vinitrd_start + initrd_len;
         vphysmap_start   = round_pgup(vinitrd_end);
         vphysmap_end     = vphysmap_start + (nr_pages * sizeof(unsigned long));
@@ -631,7 +629,7 @@ int construct_dom0(struct domain *p,
         v_end            = (vstack_end + (1<<22)-1) & ~((1<<22)-1);
         if ( (v_end - vstack_end) < (512 << 10) )
             v_end += 1 << 22; /* Add extra 4MB to get >= 512kB padding. */
-        if ( (((v_end - v_start + ((1<<L2_PAGETABLE_SHIFT)-1)) >> 
+        if ( (((v_end - dsi.v_start + ((1<<L2_PAGETABLE_SHIFT)-1)) >> 
                L2_PAGETABLE_SHIFT) + 1) <= nr_pt_pages )
             break;
     }
@@ -651,20 +649,20 @@ int construct_dom0(struct domain *p,
            " Start info:    %08lx->%08lx\n"
            " Boot stack:    %08lx->%08lx\n"
            " TOTAL:         %08lx->%08lx\n",
-           vkern_start, vkern_end, 
+           dsi.v_kernstart, dsi.v_kernend, 
            vinitrd_start, vinitrd_end,
            vphysmap_start, vphysmap_end,
            vpt_start, vpt_end,
            vstartinfo_start, vstartinfo_end,
            vstack_start, vstack_end,
-           v_start, v_end);
-    printk(" ENTRY ADDRESS: %08lx\n", vkern_entry);
+           dsi.v_start, v_end);
+    printk(" ENTRY ADDRESS: %08lx\n", dsi.v_kernentry);
 
-    if ( (v_end - v_start) > (nr_pages * PAGE_SIZE) )
+    if ( (v_end - dsi.v_start) > (nr_pages * PAGE_SIZE) )
     {
         printk("Initial guest OS requires too much space\n"
                "(%luMB is greater than %luMB limit)\n",
-               (v_end-v_start)>>20, (nr_pages<<PAGE_SHIFT)>>20);
+               (v_end-dsi.v_start)>>20, (nr_pages<<PAGE_SHIFT)>>20);
         return -ENOMEM;
     }
 
@@ -672,7 +670,7 @@ int construct_dom0(struct domain *p,
      * Protect the lowest 1GB of memory. We use a temporary mapping there
      * from which we copy the kernel and ramdisk images.
      */
-    if ( v_start < (1<<30) )
+    if ( dsi.v_start < (1<<30) )
     {
         printk("Initial loading isn't allowed to lowest 1GB of memory.\n");
         return -EINVAL;
@@ -691,7 +689,7 @@ int construct_dom0(struct domain *p,
         p->tot_pages++; p->max_pages++;
     }
 
-    mpt_alloc = (vpt_start - v_start) + alloc_start;
+    mpt_alloc = (vpt_start - dsi.v_start) + alloc_start;
 
     SET_GDT_ENTRIES(p, DEFAULT_GDT_ENTRIES);
     SET_GDT_ADDRESS(p, DEFAULT_GDT_ADDRESS);
@@ -715,9 +713,9 @@ int construct_dom0(struct domain *p,
         mk_l2_pgentry(__pa(p->mm.perdomain_pt) | __PAGE_HYPERVISOR);
     p->mm.pagetable = mk_pagetable((unsigned long)l2start);
 
-    l2tab += l2_table_offset(v_start);
+    l2tab += l2_table_offset(dsi.v_start);
     mfn = alloc_start >> PAGE_SHIFT;
-    for ( count = 0; count < ((v_end-v_start)>>PAGE_SHIFT); count++ )
+    for ( count = 0; count < ((v_end-dsi.v_start)>>PAGE_SHIFT); count++ )
     {
         if ( !((unsigned long)l1tab & (PAGE_SIZE-1)) )
         {
@@ -726,7 +724,7 @@ int construct_dom0(struct domain *p,
             *l2tab++ = mk_l2_pgentry((unsigned long)l1start | L2_PROT);
             clear_page(l1tab);
             if ( count == 0 )
-                l1tab += l1_table_offset(v_start);
+                l1tab += l1_table_offset(dsi.v_start);
         }
         *l1tab++ = mk_l1_pgentry((mfn << PAGE_SHIFT) | L1_PROT);
         
@@ -762,7 +760,7 @@ int construct_dom0(struct domain *p,
             page->u.inuse.type_info &= ~PGT_type_mask;
             page->u.inuse.type_info |= PGT_l1_page_table;
            page->u.inuse.type_info |= 
-               ((v_start>>L2_PAGETABLE_SHIFT)+(count-1))<<PGT_va_shift;
+               ((dsi.v_start>>L2_PAGETABLE_SHIFT)+(count-1))<<PGT_va_shift;
 
             get_page(page, p); /* an extra ref because of readable mapping */
         }
@@ -771,6 +769,10 @@ int construct_dom0(struct domain *p,
             l1start = l1tab = (l1_pgentry_t *)l2_pgentry_to_phys(*l2tab);
     }
 
+    /* Set up domain options */
+    if (dsi.use_writable_pagetables)
+        vm_assist(p, VMASST_CMD_enable, VMASST_TYPE_writable_pagetables);
+
     /* Set up shared-info area. */
     update_dom_time(p->shared_info);
     p->shared_info->domain_time = 0;
@@ -804,7 +806,7 @@ int construct_dom0(struct domain *p,
     {
         mfn = pfn + (alloc_start>>PAGE_SHIFT);
 #ifndef NDEBUG
-#define REVERSE_START ((v_end - v_start) >> PAGE_SHIFT)
+#define REVERSE_START ((v_end - dsi.v_start) >> PAGE_SHIFT)
         if ( pfn > REVERSE_START )
             mfn = (alloc_end>>PAGE_SHIFT) - (pfn - REVERSE_START);
 #endif
@@ -854,7 +856,7 @@ int construct_dom0(struct domain *p,
     shadow_mode_enable(&p->mm, SHM_test); 
 #endif
 
-    new_thread(p, vkern_entry, vstack_end, vstartinfo_start);
+    new_thread(p, dsi.v_kernentry, vstack_end, vstartinfo_start);
 
     return 0;
 }
index f64d21e7117611124345ef0cedf83c2e1c38c083..d8ac21a68831a99f1c1381cf1bfa5e01fa667d5d 100644 (file)
@@ -308,3 +308,25 @@ int final_setup_guestos(struct domain *p, dom0_builddomain_t *builddomain)
         xfree(c);
     return rc;
 }
+
+long vm_assist(struct domain *p, unsigned int cmd, unsigned int type)
+{
+    if ( type > MAX_VMASST_TYPE )
+        return -EINVAL;
+
+    switch ( cmd )
+    {
+    case VMASST_CMD_enable:
+        set_bit(type, &p->vm_assist);
+        if (vm_assist_info[type].enable)
+            (*vm_assist_info[type].enable)(p);
+        return 0;
+    case VMASST_CMD_disable:
+        clear_bit(type, &p->vm_assist);
+        if (vm_assist_info[type].disable)
+            (*vm_assist_info[type].disable)(p);
+        return 0;
+    }
+
+    return -ENOSYS;
+}
index ae20c04f6f348a36960298c5340326f92fd1d200..7f5a11e351930ee4a2b2997d1a62e17fc5bc18fb 100644 (file)
@@ -18,10 +18,7 @@ static inline int is_loadable_phdr(Elf_Phdr *phdr)
 
 int parseelfimage(char *elfbase, 
                   unsigned long elfsize,
-                  unsigned long *pvirtstart,
-                  unsigned long *pkernstart,
-                  unsigned long *pkernend,
-                  unsigned long *pkernentry)
+                  struct domain_setup_info *dsi)
 {
     Elf_Ehdr *ehdr = (Elf_Ehdr *)elfbase;
     Elf_Phdr *phdr;
@@ -109,13 +106,16 @@ int parseelfimage(char *elfbase,
         return -EINVAL;
     }
 
-    *pvirtstart = kernstart;
+    dsi->v_start = kernstart;
     if ( (p = strstr(guestinfo, "VIRT_BASE=")) != NULL )
-        *pvirtstart = simple_strtoul(p+10, &p, 0);
+        dsi->v_start = simple_strtoul(p+10, &p, 0);
 
-    *pkernstart = kernstart;
-    *pkernend   = kernend;
-    *pkernentry = ehdr->e_entry;
+    if ( (p = strstr(guestinfo, "PT_MODE_WRITABLE")) != NULL )
+        dsi->use_writable_pagetables = 1;
+
+    dsi->v_kernstart = kernstart;
+    dsi->v_kernend   = kernend;
+    dsi->v_kernentry = ehdr->e_entry;
 
     return 0;
 }
index 9b2a3cd70ce11bc2147f93048e42d0720f119621..1baef5caa9f4ed3fb8a5e08083a28e65a45df017 100644 (file)
@@ -365,24 +365,7 @@ long do_xen_version(int cmd)
 
 long do_vm_assist(unsigned int cmd, unsigned int type)
 {
-    if ( type > MAX_VMASST_TYPE )
-        return -EINVAL;
-
-    switch ( cmd )
-    {
-    case VMASST_CMD_enable:
-        set_bit(type, &current->vm_assist);
-        if (vm_assist_info[type].enable)
-            (*vm_assist_info[type].enable)();
-        return 0;
-    case VMASST_CMD_disable:
-        clear_bit(type, &current->vm_assist);
-        if (vm_assist_info[type].disable)
-            (*vm_assist_info[type].disable)();
-        return 0;
-    }
-
-    return -ENOSYS;
+    return vm_assist(current, cmd, type);
 }
 
 long do_ni_hypercall(void)
index 894130d1439f3c3d397f50bbf8bfb9db9f58c3ca..ec0f88cee6cd17631e3f71932e39f890d3b76a7d 100644 (file)
@@ -363,8 +363,8 @@ int memguard_is_guarded(void *p);
 
 
 typedef struct {
-    void       (*enable)(void);
-    void       (*disable)(void);
+    void       (*enable)(struct domain *);
+    void       (*disable)(struct domain *);
 } vm_assist_info_t;
 extern vm_assist_info_t vm_assist_info[];
 
index 2abd8a2206251214bac6da57af460a57e02931da..9e474367b7919a45927d951f94a41f3d40215946 100644 (file)
@@ -525,8 +525,6 @@ typedef struct {
 #endif
 
 extern int loadelfimage(char *);
-extern int parseelfimage(
-    char *, unsigned long, unsigned long *,
-    unsigned long *, unsigned long *, unsigned long *);
+extern int parseelfimage(char *, unsigned long, struct domain_setup_info *);
 
 #endif /* __XEN_ELF_H__ */
index e9893a2f6f08840f22850d6ba0934b476c9568fb..362ea007a1f0ad6776c8bfcd46ba235655b3e122 100644 (file)
 #define reserve_bootmem(_p,_l) \
 printk("Memory Reservation 0x%lx, %lu bytes\n", (_p), (_l))
 
+struct domain;
+
 /* kernel.c */
 #define printk printf
 void printf(const char *format, ...);
 void panic(const char *format, ...);
+long vm_assist(struct domain *, unsigned int, unsigned int);
 
 /* vsprintf.c */
 extern int sprintf(char * buf, const char * fmt, ...)
index 51fb070673422553d40a7fd03790539d65ce477b..99368a7a12d3f8b5c1a3ae760b14caf32c29b899 100644 (file)
@@ -146,6 +146,16 @@ struct domain
     atomic_t pausecnt;
 };
 
+struct domain_setup_info
+{
+    unsigned long v_start;
+    unsigned long v_kernstart;
+    unsigned long v_kernend;
+    unsigned long v_kernentry;
+
+    unsigned int use_writable_pagetables;
+};
+
 #include <asm/uaccess.h> /* for KERNEL_DS */
 
 extern struct domain idle0_task;